#
# Adsense.py
# Copyright (C) otacon 2010 <orfeo18@gmail.com>
# 
# AdSense-Monitor is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# AdSense-Monitor is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.

import binascii
import re
import sys
import urllib
import socket
import urllib2 
import cookielib
import Report

socket.setdefaulttimeout(20)


class Adsense:

    def __init__( self ):
        '''
        Constructor
        '''
        
        jar = cookielib.CookieJar()
        handler = urllib2.HTTPCookieProcessor(jar)
        opener = urllib2.build_opener(handler)
        urllib2.install_opener(opener)
        #self.handle = urllib2.HTTPHandler(debuglevel=1)
 
    def login( self , Email , Passwd ):
        '''
        Method to login to Adsense Account page
        '''
        # /adsense/
        #Download adsense webpage
        page_source = self._execute_request('https://www.google.com/adsense')
        if not page_source:
            return False
        # /adsense/login-box.js
        #Download Loginbox, inside this box there is the URL to post login data
        page_source = self._execute_request('https://www.google.com/adsense/login-box.js')
        if not page_source:
            return False
        #A little conversion of data inside javascript URL
        page_source = page_source.replace( "\\75" , '=' )
        page_source = page_source.replace( "\\075" , '=' )
        page_source = page_source.replace( "\\42" , '"' )
        page_source = page_source.replace( "\\46" , '&' )

        reg = re.compile( 'src="(.*?)"',re.DOTALL )
        url = reg.search( page_source )
        if url == None:
            return False
        url = url.group(1).replace( '&amp;' , '&' )
        
        page_source = self._execute_request(url)
        if not page_source:
            return False
        # /accounts/ServiceLoginBoxAuth
        #Fetching hidden input in html source
        parameters = {}
        reg = re.compile( '<input.*?type="hidden".*?name=[\'"](.*?)[\'"].*?value="(.*?)".*?>',re.DOTALL )
        values = reg.findall( page_source )
        for name in values:
            parameters[name[0]] = name[1]
        parameters["Email"] = Email
        parameters["Passwd"] = Passwd
        parameters["null"] = "Sign in"
        
        # POST -> ../accounts/ServiceLoginBoxAuth/
        # Authenticating
        
        page_source = self._execute_request('https://www.google.com/accounts/ServiceLoginBoxAuth',parameters)
        if not page_source:
            return False
        reg = re.compile( '"(https://www.google.com/accounts/CheckCookie?.*?)"',re.DOTALL )
        url = reg.search( page_source )
        if url == None:
            return False
        
        url = url.group(1).replace( '&amp;' , '&' )

        #Moving to /accounts/CheckCookie
        page_source = self._execute_request(url)
        if not page_source:
            return False
        #Checking Connection status
        if page_source.find('<a href="/adsense/signout">') >-1:
            return True

        #Managing redirects
        reg = re.compile( 'location\.replace\("(.*?)"\)',re.DOTALL )
        url = reg.search( page_source )
        if url == None:
            return False
        
        url = url.group(1)
        
        #Managing binary data
        while url.find('\\x') > -1:
            position = url.find('\\x')
            hex_string = url[position+2:position+4]
            int_value = int(hex_string,16)
            url=url.replace('\\x' + hex_string,chr(int_value))
        page_source = self._execute_request(url)
        if not page_source:
            return False
        if page_source.find('<a href="/adsense/signout">') > -1:
            return True
        
        return False

    def logout(self):
        '''
        Method to logout from adsense
        '''
        self._execute_request("https://www.google.com/adsense/signout")

    def _execute_request(self , url , data=None):
        '''
        Little Workaround to empty page buffer on every request
        '''
        success = False
        attempts = 0
        while not success and attempts < 3:
            if data:
                try:
                    content = urllib2.urlopen(url,urllib.urlencode(data))
                    content = content.read()
                    success = True
                except:
                    attempts = attempts + 1
            else:
                try:
                    content = urllib2.urlopen(url)
                    content = content.read()
                    success = True
                except:
                    attempts = attempts + 1

        if success:
            return content
        else:
            print "Failed to obtain " + url
            return False
     
    def get_all_time(self):
        '''
        Generates the CSV output for "All Time" Adsense time-lapse
        '''
        request = self._execute_request("https://www.google.com/adsense/report/aggregate?product=afc&dateRange.dateRangeType=simple&dateRange.simpleDate=alltime&reportType=property&groupByPref=date&outputFormat=TSV_EXCEL&unitPref=page" )
        decoded_request = self.decode_request(request)
        return decoded_request
        
     
    def get_today(self):
        '''
        Generates the CSV output for "Today" Adsense time-lapse
        '''
        request = self._execute_request("https://www.google.com/adsense/report/aggregate?product=afc&dateRange.dateRangeType=simple&dateRange.simpleDate=today&reportType=property&groupByPref=date&outputFormat=TSV_EXCEL&unitPref=page")
        decoded_request = self.decode_request(request)
        return Report.parse_from_csv(decoded_request)
         
    def get_last_month(self):
        '''
        Generates the CSV output for "Last Month" Adsense time-lapse
        '''
        request = self._execute_request("https://www.google.com/adsense/report/aggregate?product=afc&dateRange.dateRangeType=simple&dateRange.simpleDate=thismonth&reportType=property&groupByPref=date&outputFormat=TSV_EXCEL&unitPref=page")
        decoded_request = self.decode_request(request)
        return decoded_request
        
    def get_custom_data(self,start , end , reverseSort=False):
        '''
        Generates the CSV output for a custom Adsense time-lapse
        '''
        params = dict()
        params["reverseSort"] = False
        params["sortColumn"] = 0
        params["outputFormat"] = "TSV_EXCEL"
        params["storedReportId"] = -1
        params["isOldReport"] = False
        params["piStart"] = -1
        params["product"] = "afc"
        params["dateRange.simpleDate"] = "today"
        params["dateRange.dateRangeType"] = "custom"
        params["dateRange.customDate.start.day"] = 25
        params["dateRange.customDate.start.month"] = 01
        params["dateRange.customDate.start.year"] = 2010
        params["dateRange.customDate.end.day"] = 25
        params["dateRange.customDate.end.month"] = 02
        params["dateRange.customDate.end.year"] = 2010
        params["unitPref"] = "page"
        params["reportType"] = "property"
        params["searchField"] = ""
        params["groupByPref"] = "date"
        params["radlingChoice"] = "COMBINED"

        request = self._execute_request("https://www.google.com/adsense/report/aggregate",params)
        decoded_request = self.decode_request(request)
        return decoded_request

    def decode_request(self , report):
        report = report.decode('utf_16')
        return str(report)
